package com.seven.smartsnmp.discover;

import com.seven.smartsnmp.base.SNMPSysConfig;
import com.seven.smartsnmp.discover.service.*;
import com.seven.smartsnmp.snmp.SNMPFactory;
import com.seven.smartsnmp.snmp.SNMPTarget;

import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;

public class DiscoverAPI {

    private static DiscoverAPI discoverServiceAPI;

    /**
     * 初始化
     */
    private DiscoverAPI() {
        try {
            SNMPFactory.init();
        } catch (Exception exception) {
            System.out.println("init snmpService erro:" + exception.getMessage());
            exception.printStackTrace();
        }

    }

    /**
     * 获取发现设备api接口
     *
     * @return
     */
    public static DiscoverAPI getDiscoverAPI() {

        if (discoverServiceAPI == null) {
            synchronized (DiscoverAPI.class) {
                if (discoverServiceAPI == null) {
                    discoverServiceAPI = new DiscoverAPI();
                }
            }
        }

        return discoverServiceAPI;
    }

    /**
     * 根据ip查询
     *
     * @param ip
     * @param snmpTargets
     * @param isUsePing
     * @return
     */
    public ConcurrentLinkedQueue<DeviceInfo> searchDevice(String ip, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        SNMPSysConfig.SnmpRetry = 2;
        ConcurrentLinkedQueue deviceInfo = new ConcurrentLinkedQueue();
        try {
            deviceInfo = (new SearchNodeService()).searchDevice(ip, snmpTargets, isUsePing);
            return deviceInfo;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SNMPSysConfig.SnmpRetry = 0;
        }
        return deviceInfo;
    }

    /**
     * @param ipQueue
     * @param snmpTargets
     * @param isUsePing
     * @return
     */
    public ConcurrentLinkedQueue<DeviceInfo> searchDeviceByNetList(ConcurrentLinkedQueue<String> ipQueue, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        SNMPSysConfig.SnmpRetry = 2;
        ConcurrentLinkedQueue deviceInfos = new ConcurrentLinkedQueue();
        try {
            deviceInfos = (new SearchNodeService()).searchDeviceByNetList(ipQueue, snmpTargets, isUsePing);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SNMPSysConfig.SnmpRetry = 0;
        }
        return deviceInfos;
    }

    /**
     * 根据ip区间查询设备
     *
     * @param startIp
     * @param endIp
     * @param snmpTargets
     * @param isUsePing
     * @return
     */
    public ConcurrentLinkedQueue<DeviceInfo> searchDevice(String startIp, String endIp, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        SNMPSysConfig.SnmpRetry = 2;
        ConcurrentLinkedQueue deviceInfos = new ConcurrentLinkedQueue();
        try {
            deviceInfos = (new SearchNodeService()).searchDevice(startIp, endIp, snmpTargets, isUsePing);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SNMPSysConfig.SnmpRetry = 0;
        }
        return deviceInfos;
    }

    /**
     * 根据ip查询
     *
     * @param ipQueue
     * @param snmpTargets
     * @param isUsePing
     * @return
     */
    public ConcurrentLinkedQueue<DeviceInfo> searchDeviceByIPList(ConcurrentLinkedQueue<String> ipQueue, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        SNMPSysConfig.SnmpRetry = 2;
        ConcurrentLinkedQueue concurrentLinkedQueue;
        try {
            ConcurrentLinkedQueue deviceInfoConcurrentLinkedQueue = (new SearchNodeService()).searchDeviceByIPList(ipQueue, snmpTargets, isUsePing);
            return deviceInfoConcurrentLinkedQueue;
        } catch (Exception e) {
            concurrentLinkedQueue = new ConcurrentLinkedQueue();
        } finally {
            SNMPSysConfig.SnmpRetry = 0;
        }
        return concurrentLinkedQueue;
    }

    /**
     * 路由搜索网段
     *
     * @param ipQueue  ip队列
     * @param snmpTargets
     * @param isUsePing 是否使用ping
     * @param depth     便利深度 最大8
     * @param maxNode 最多设备
     * @return
     */
    public ConcurrentLinkedQueue<DeviceInfo> searchDeviceByIPRoaming(ConcurrentLinkedQueue<String> ipQueue, List<SNMPTarget> snmpTargets, boolean isUsePing, int depth, int maxNode) {
        SNMPSysConfig.SnmpRetry = 1;
        ConcurrentLinkedQueue deviceInfos = new ConcurrentLinkedQueue();
        try {
            deviceInfos = (new SearchDeviceByIPRoaming()).searchDeviceByIPRoaming(ipQueue, snmpTargets, isUsePing, depth, maxNode);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SNMPSysConfig.SnmpRetry = 0;
        }
        return deviceInfos;
    }

    public ConcurrentLinkedQueue<DeviceInfo> searchDeviceByRouterNet(String ipNet, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        SNMPSysConfig.SnmpRetry = 2;
        ConcurrentLinkedQueue deviceInfos = new ConcurrentLinkedQueue();
        try {
            deviceInfos = (new SearchRouterInfoService()).searchDeviceByRouterNet(ipNet, snmpTargets, isUsePing);
        } catch (Exception e) {
        } finally {
            SNMPSysConfig.SnmpRetry = 0;
        }
        return deviceInfos;
    }

    /**
     * 获取指定设备信息
     *
     * @param ip
     * @param snmpTargets
     * @param isUsePing
     * @return
     */
    public DeviceInfo getDeviceBasicInfo(String ip, List<SNMPTarget> snmpTargets, boolean isUsePing) {
        try {
            return (new SearchBasicDeviceInfoService()).getDeviceBasicInfo(ip, snmpTargets, isUsePing);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 发现设备关联关系
     *
     * @param deviceInfos
     * @return
     */
    public List<LinkInfo> searchLinkInfo(CopyOnWriteArrayList<DeviceInfo> deviceInfos) {
        SNMPSysConfig.SnmpRetry = 1;
        List<LinkInfo> list = new CopyOnWriteArrayList();
        try {
            list = (new SearchTopoRelationService()).createAllLinks(deviceInfos);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            SNMPSysConfig.SnmpRetry = 0;
        }
        return list;
    }
}
